package timing.ukulele.third.msgChannel.action.send;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import timing.ukulele.third.dictionary.msg.MsgChannelType;
import timing.ukulele.third.msgChannel.model.SendTaskInfo;
import timing.ukulele.third.msgChannel.model.content.CommonContentParamModel;
import timing.ukulele.third.msgChannel.model.content.ContentModel;
import timing.ukulele.third.msgChannel.param.SendMessageParam;
import timing.ukulele.third.msgChannel.utils.ContentHolderUtil;
import timing.ukulele.third.msgChannel.utils.TaskInfoUtils;
import timing.ukulele.third.persistent.msg.MessageTemplate;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @description 可变参数和默认值处理
 * @author zh
 */
@Slf4j
@Service
public class SendAssembleAction {

    private static final String PARAM_FILED_NAME = "paramList";
    private static final String LINK_NAME = "url";

    public SendTaskInfo process(MessageTemplate messageTemplate, SendMessageParam sendMessageParam) {

        SendTaskInfo sendTaskInfo = new SendTaskInfo();
        // 模板信息
        sendTaskInfo.setMessageTemplateId(messageTemplate.getId());
        sendTaskInfo.setSendChannel(messageTemplate.getSendChannel());
        sendTaskInfo.setSendAccountId(messageTemplate.getSendAccountId());
        // 处理接受者为set集合
        sendTaskInfo.setReceiver(new HashSet<>(Arrays.asList(sendMessageParam.getReceiver().split(String.valueOf(StrPool.C_COMMA)))));
        // 处理渠道发送内容模型
        sendTaskInfo.setContentModel(getContentModelValue(messageTemplate, sendMessageParam));

        return sendTaskInfo;
    }

    /**
     * 获取 contentModel，替换模板msgContent中占位符信息
     */
    private ContentModel getContentModelValue(MessageTemplate messageTemplate, SendMessageParam sendMessageParam) {

        // 得到真正的ContentModel类型
        Integer sendChannel = messageTemplate.getSendChannel();
        Class<? extends ContentModel> contentModelClass = MsgChannelType.getChanelModelClassByCode(sendChannel);

        // 得到模板的 msgContent 和 入参
        Map<String, String> variables = sendMessageParam.getVariables();
        JSONObject jsonObject = JSON.parseObject(messageTemplate.getMsgContent());
        // 扩展参数
        Map<String, String> extra = sendMessageParam.getExtra();

        // 通过反射组装出contentModel
        Field[] fields = ReflectUtil.getFields(contentModelClass);
        ContentModel contentModel = ReflectUtil.newInstance(contentModelClass);

        for (Field field : fields) {
            String originValue = jsonObject.getString(field.getName());
            ReflectUtil.setFieldValue(contentModel, field, originValue);
            // 如果外部参数为空，那么直接跳过后续处理
            if (variables == null) {
                continue;
            }
            // 根据系统占位符进行替换值处理
            if (CharSequenceUtil.isNotBlank(originValue)) {
                String resultValue = ContentHolderUtil.replacePlaceHolder(originValue, variables);
                Object resultObj = JSON.isValid(resultValue) ? JSONObject.parseObject(resultValue,field.getType()) : resultValue;
                ReflectUtil.setFieldValue(contentModel, field, resultObj);
            }
            // 外层默认值处理，如果外部传参，以外部传参为准，反之以默认值为准
            String paramValue = variables.get(field.getName());
            if (CharSequenceUtil.isNotBlank(paramValue)) {
                ReflectUtil.setFieldValue(contentModel, field, paramValue);
            }
            // 内层默认值处理，默认以paramList参数为准，以CommonContentParamModel对象进行序列化，系统规定！
            if (field.getName().equals(PARAM_FILED_NAME)) {
                String paramStr = (String) ReflectUtil.getFieldValue(contentModel, field);
                if(paramStr == null) {
                    continue;
                }
                List<CommonContentParamModel> paramList = JSONArray.parseArray(paramStr, CommonContentParamModel.class);
                for (CommonContentParamModel commonContentParamModel : paramList) {
                    // 如果外部传参，以外部传参为准，反之以默认值为准
                    // 首先判断映射字段
                    String innerMappingParamValue = variables.get(commonContentParamModel.getMappingFiled());
                    if(innerMappingParamValue != null) {
                        commonContentParamModel.setValueData(innerMappingParamValue);
                    }
                    // 在判断原生字段
                    String innerParamValue = variables.get(commonContentParamModel.getKey());
                    if(innerParamValue != null) {
                        commonContentParamModel.setValueData(innerParamValue);
                    }
                }
                ReflectUtil.setFieldValue(contentModel, field, JSON.toJSONString(paramList));
            }
        }

        // 如果 url 字段存在，则在url拼接对应的埋点参数
        String url = (String) ReflectUtil.getFieldValue(contentModel, LINK_NAME);
        if (CharSequenceUtil.isNotBlank(url)) {
            String resultUrl = TaskInfoUtils.generateUrl(url, messageTemplate.getId(), messageTemplate.getTemplateType());
            ReflectUtil.setFieldValue(contentModel, LINK_NAME, resultUrl);
        }
        // 外部扩展参数透传下去，有些渠道会使用
        contentModel.setExtra(extra);
        return contentModel;
    }

}
